#include "InspectorDialog.h"
#include "ui_InspectorDialog.h"

#include <QtCore>
#include <QInputDialog>

// InspectorDataModel implementation

QVariant InspectorDataModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole)
		return QVariant();

	if (orientation == Qt::Horizontal) {
		switch (section) {
		case 0:
			return tr("Key");

		case 1:
			return tr("Value");

		default:
			return QVariant();
		}
	}
	return QVariant();
}

Qt::ItemFlags InspectorDataModel::flags(const QModelIndex &index) const
{
	if (!index.isValid())
		return Qt::ItemIsEnabled;

	return QAbstractTableModel::flags(index);
}

int InspectorDataModel::rowCount(const QModelIndex & parent) const
{
	Q_UNUSED(parent);
	return listOfPairs.size();
}

int InspectorDataModel::columnCount(const QModelIndex & parent) const
{
	Q_UNUSED(parent);
	return 2;
}

QVariant InspectorDataModel::data(const QModelIndex & index, int role) const
{
	if (!index.isValid())
		return QVariant();

	if (index.row() >= listOfPairs.size() || index.row() < 0)
		return QVariant();

	if (role == Qt::DisplayRole) {
		QPair<QString, QString> pair = listOfPairs.at(index.row());

		if (index.column() == 0)
			return pair.first;
		else if (index.column() == 1)
			return pair.second;
	}
	
	return QVariant();
}

bool InspectorDataModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
	if (index.isValid() && role == Qt::DisplayRole) {
		int row = index.row();

		QPair<QString, QString> p = listOfPairs.value(row);

		if (index.column() == 0)
			p.first = value.toString();
		else if (index.column() == 1)
			p.second = value.toString();
		else
			return false;

		listOfPairs.replace(row, p);
		emit(dataChanged(index, index));

		return true;
	}

	return false;
}

void InspectorDataModel::setData(const QMap<QString, QString>& data)
{
	QModelIndex modelIndex = QModelIndex();
	
	int previousSize = listOfPairs.size();
	if (previousSize > 0) {
		beginRemoveRows(modelIndex, 0, previousSize - 1);
		listOfPairs.clear();
		endRemoveRows();
	}
	
	if (data.size() == 0)
		return;
	
	beginInsertRows(modelIndex, 0, data.size() - 1);
	QMapIterator<QString, QString> iter(data);
	while (iter.hasNext()) {
		iter.next();
		QPair<QString, QString> p(iter.key(), iter.value());
		listOfPairs << p;
	}
	endInsertRows();
}


// InspectorDialog implementation

InspectorDialog::InspectorDialog(QWidget *parent) :
    QDialog(parent), horizontalScale(1.0f), verticalScale(1.0f),
    m_ui(new Ui::InspectorDialog)
{
    m_ui->setupUi(this);
	scaleTimer = new QTimer(this);
	scaleTimer->setInterval(1000 / 30);
	scaleTimer->setSingleShot(false);
	
	connect(scaleTimer, SIGNAL(timeout()), this, SLOT(updateScale()));
	
	panTimer = new QTimer(this);
	panTimer->setInterval(1000 / 30);
	panTimer->setSingleShot(false);
	
	connect(panTimer, SIGNAL(timeout()), this, SLOT(updatePan()));
	
	m_ui->tableView->setModel(&model);
}

InspectorDialog::~InspectorDialog()
{
    delete m_ui;
}

void InspectorDialog::changeEvent(QEvent *e)
{
    switch (e->type()) {
    case QEvent::LanguageChange:
        m_ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void InspectorDialog::setData(const QMap<QString, QString>& data)
{
	model.setData(data);
	m_ui->tableView->resizeColumnsToContents();
	m_ui->tableView->resizeRowsToContents();
}

void InspectorDialog::centerHorizontalSlider()
{
	m_ui->horizontalScaleSlider->setValue(0);
}

void InspectorDialog::centerVerticalSlider()
{
//	m_ui->verticalScaleSlider->setValue(0);
}

void InspectorDialog::setHorizontalScalingSpeed(int speed)
{
	if (speed == 0)
		scaleTimer->stop();
	else if (!scaleTimer->isActive())
		scaleTimer->start();
}

void InspectorDialog::setVerticalScalingSpeed(int speed)
{
	if (speed == 0)
		scaleTimer->stop();
	else if (!scaleTimer->isActive())
		scaleTimer->start();
}

void InspectorDialog::resetScaling()
{
	scaleTimer->stop();
	horizontalScale = 1.0f;
	verticalScale = 1.0f;
	emit scaleChanged(horizontalScale, verticalScale);
}

void InspectorDialog::updateScale()
{
	horizontalScale *= getMultiplier(m_ui->horizontalScaleSlider->value());
//	verticalScale *= getMultiplier(m_ui->verticalScaleSlider->value());
	verticalScale = 1.0f;
	emit scaleChanged(horizontalScale, verticalScale);
}


void InspectorDialog::centerHorizontalPositionSlider()
{
	m_ui->horizontalPositionSlider->setValue(0);
}

void InspectorDialog::setHorizontalPanSpeed(int speed)
{
	if (speed == 0)
		panTimer->stop();
	else if (!panTimer->isActive())
		panTimer->start();
}

void InspectorDialog::updatePan()
{
	emit moveChanged(getStep(m_ui->horizontalPositionSlider->value()), 0.0f);
}

void InspectorDialog::lookAtPast()
{
	emit panChanged(58.0f);
}

void InspectorDialog::lookAtPresent()
{
	emit panChanged(0.0f);
}

void InspectorDialog::lookAtFuture()
{
	emit panChanged(302.0f);
}

void InspectorDialog::search()
{
	bool ok;
	QString state = QInputDialog::getText(this, "Search", "Thread state:", QLineEdit::Normal, "", &ok);
	if (ok && !state.isEmpty())
		emit dummySearch(state);
}

void InspectorDialog::focus()
{
	emit focusSelection();
}

void InspectorDialog::clear()
{
	emit clearSelectionOrSearch();
}

void InspectorDialog::moveTo()
{
	bool ok;
	double position = QInputDialog::getDouble(this, "Move to", "Position:", 0, 0, 2147483647, 1, &ok);
	if (ok)
		emit moveToPosition(position);
}

void InspectorDialog::updateInspectorData(const QMap<QString, QString>& data)
{
	setData(data);
}

float InspectorDialog::getStep(int speed) const
{
	float x = (speed < 0 ? -speed : speed) + 1.0f;
	float step = powf(10.0f, x / 2000.0f) / 10.0f;
	return (speed < 0 ? -step : step);
}
